Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GATT notifications : use setCharacteristicNotification from Android 4.3 #307

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

fmhun
Copy link

@fmhun fmhun commented Jul 11, 2016

Hi,

This pull request solve a critical bug in gatt notification. I experienced the issue #294 on Android 5.1 (Nexus 6) and Android 6.0 (Samsung S6).

In my case, the subscribe success callback was called first with the status subscribed but was never called with the status subscribedResult. After receiving the status subscribed, the subscribe error callback was called with an isDisconnected error.

The Android documentation (https://developer.android.com/guide/topics/connectivity/bluetooth-le.html#notification) say that we must call the BluetoothGatt#setCharacteristicNotification() to enable/disable characteristic notification.

This method call is missing in the BluetoothLePlugin#subscribeAction() and BluetoothLePlugin#unsubscribeAction() methods.

Note : The BluetoothGatt#setCharacteristicNotification() method is available in the SDK from jelly bean.

…bscribe to notification from Android 4.3.
@randdusing
Copy link
Owner

@fmhun The setCharacteristicNotification calls are within the onDescriptorWrite callback already. Are you sure this is the cause of your error?

@fmhun
Copy link
Author

fmhun commented Jul 12, 2016

You are right ... I can't really explain what's happening but adding the setCharacteristicNotification call in subscribeAction and unsubscribeAction fix the bug on my devices.

I also removed setCharacteristicNotification call from onDescriptorWrite callback and it works fine. Thus, I think we should keep setCharacteristicNotification calls onDescriptorWrite just in case.

@randdusing
Copy link
Owner

I remember looking into this when originally working on the plugin, but it's been two years. Let me take a look. The Android example app has it call setCharacteristicNotification first. It's also only writing the descriptor if it's a heart beat UUID... Since this was originally developed for a heart rate related app, maybe my code only works for heart rate monitors. I'm surprised no one else has faced the issue... What type of device are you connecting to?

@fmhun
Copy link
Author

fmhun commented Jul 13, 2016

Hi @randdusing,

I don't think I'm the only one facing this issue, @kgillespieanaren reported the bug in issue #266. Sorry for having referenced the #294 it was a mistake ...

I'm working with a custom and not commercialized BLE device. The device works perfectly on iOS with your plugin.

@zmoshansky
Copy link

zmoshansky commented Nov 10, 2017

AFAIK, There's potentially a race condition between when the android device writes to the client characteristic configuration descriptor (CCCD) on the peripheral and enabling notifications on central.

ex.) Current workflow without this branch is outlined below. If a notification/indication is sent before step 2 or 3, I believe the Android device would ignore it; Resulting in behaviour witnessed above.

  1. Android writes CCCD
    1a.) AFAIK, Peripheral is now able to start sending data
  2. Android receives onDescriptorWrite
  3. Android calls setCharacteristicNotification
  4. Notifications/Indications are receivable by central.

A better solution may involve:

  1. Android calls setCharacteristicNotification(true)
  2. Notifications/Indications are receivable by central (Although none should be sent until step 3)
  3. Android writes CCCD
  4. Android receives onDescriptorWrite
  • If the descriptor couldn't be written, revert setCharacteristicNotification(false)

Edit:

https://stackoverflow.com/a/38807905/1404126:

Here is an excerpt from the O'Reilly book "Getting Started With Bluetooth Low Energy":

To enable notifications on Android, you normally have to locally enable the notification for the particular characteristic you are interested in.

Once that’s done, you also have to enable notifications on the peer device by writing to the device’s client characteristic configuration descriptor (CCCD)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants